package com.meizi.codegenerate.generate.clien.application.service.fallback;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.stmt.ReturnStmt;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.meizi.codegenerate.constant.JavaClassNameConstant;
import com.meizi.codegenerate.constant.TableNameConstant;
import com.meizi.codegenerate.entity.ProjectPositionEntity;
import com.meizi.codegenerate.entity.TablesEntity;
import com.meizi.codegenerate.packagegenerate.PackageGenerate;
import com.meizi.codegenerate.utils.AttributeConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;

/**
 * @author pc
 * @date 2024/1/4 - 14:54 - 星期四
 * @project lambda
 * @package com.meizi.codegenerate.generate.clien.application.service.fallback
 * @by GGbomd猪猪侠
 */
@Slf4j
public class FallbackFactoryGenerate {

    /**
     * 创建fallback
     * @throws IOException
     */
    public static void createFallback (String tableName, TablesEntity tablesComment,
                                       ProjectPositionEntity projectPosition, String feignClientName) throws IOException {

        // 在相应的路径下创建对应的文件
        String serviceUrl = PackageGenerate.obtainFallbackUrl(projectPosition);

        //获取Feign java类名
        String className = AttributeConvertUtils.tableNameToJava
                (tableName, TableNameConstant.TABLE_PREFIX, true)
                + JavaClassNameConstant.FALLBACK_FACTORY;
        // 获取完成的文件路径创建文件
        String fullPath = serviceUrl + className + TableNameConstant.JAVA;
        log.info("创建 application 下FallbackFactory路径 fullPath = {}", fullPath);

        CompilationUnit compilationUnit = new CompilationUnit();
        // 添加package
        compilationUnit.setPackageDeclaration(PackageGenerate.fallbackPackage(projectPosition));

        compilationUnit.addImport("feign.hystrix.FallbackFactory");
        compilationUnit.addImport("org.springframework.stereotype.Component");

        // 添加接口文件
        ClassOrInterfaceDeclaration declaration = compilationUnit.addClass(className).setPublic(true);
        //添加类级别注释
        declaration.setJavadocComment(tablesComment.getTableComment() + " FallbackFactory");

        // 添加类级别注解
        declaration.addAnnotation(Component.class);
        // 实现 FallbackFactory
        ClassOrInterfaceType fallbackFactoryType = new ClassOrInterfaceType(FallbackFactory.class.getSimpleName());
        ClassOrInterfaceType feignType = new ClassOrInterfaceType(feignClientName);
        fallbackFactoryType.setTypeArguments(feignType);
        declaration.addImplementedType(fallbackFactoryType);

        // 生成方法
        MethodDeclaration create = new MethodDeclaration();
        create.setType(feignClientName);
        create.setName("create");
        create.setModifiers(Modifier.Keyword.PUBLIC);
        create.addParameter(new Parameter(new ClassOrInterfaceType(null, Throwable.class.getSimpleName()), "cause"));
        create.addAnnotation(Override.class);
        // 创建返回语句
        ReturnStmt returnStmt = new ReturnStmt(new NameExpr("null"));
        create.getBody().ifPresent(body -> body.addStatement(returnStmt));
        declaration.addMember(create);

        log.info("生成FallbackFactory接口 compilationUnit = {}", compilationUnit.toString());

        /**
         * 把字符串写入文件
         * 参数1：需要写入的文件，如果文件不存在，将自动创建。  参数2：需要写入的内容
         * 参数3：编码格式     参数4：是否为追加模式（ ture: 追加模式，把字符串追加到原内容后面）
         */
        FileUtils.writeStringToFile(new File(fullPath), compilationUnit.toString(), "UTF-8", false);
    }

}
